package com.lbiuse.wx.api;

import com.lbiuse.wx.bean.pay.PrePayInfo;
import com.lbiuse.wx.bean.pay.PrePayResult;
import com.lbiuse.wx.bean.pay.WechatOrderQuery;
import com.lbiuse.wx.bean.pay.WechatOrderQueryReulst;
import com.lbiuse.wx.util.MD5Util;
import com.lbiuse.wx.util.MapUtil;
import com.lbiuse.wx.util.WechatConfigUtil;
import com.lbiuse.wx.util.WxHttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.TreeMap;

@Slf4j
public class PayAPI {
    //生成预支付订单地址
    private static String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    //查询订单地址
    private static String ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * 生成预支付订单
     *
     * @return
     */
    public static PrePayResult createPerOrder(PrePayInfo payinfo) throws Exception {
        payinfo.setAppId(WechatConfigUtil.getAppId());
        payinfo.setMch_id(WechatConfigUtil.getShopId());
        payinfo.setNotify_url(WechatConfigUtil.getPayNotifyUrl());
        payinfo.setNonce_str(MD5Util.CreateNoncestr().toUpperCase());
        String xml = getPackage(payinfo);
        log.debug("prePay xml date:{}", xml);
        return WxHttpUtils.postForXml(UNIFIEDORDER_URL, xml, PrePayResult.class);

    }

    /**
     * 查询微信订单
     *
     * @return
     */
    public static WechatOrderQueryReulst queryOrder(WechatOrderQuery wechatOrderQuery) throws Exception {
        wechatOrderQuery.setAppid(WechatConfigUtil.getAppId());
        wechatOrderQuery.setMch_id(WechatConfigUtil.getShopId());
        wechatOrderQuery.setNonce_str(MD5Util.CreateNoncestr().toUpperCase());
        String xml = getPayXml(MapUtil.bean2TreeMap(wechatOrderQuery));
        log.debug("prePay xml date:{}", xml);
        return WxHttpUtils.postForXml(ORDER_QUERY, xml, WechatOrderQueryReulst.class);

    }

    /**
     * 根据本地orderId查询微信订单
     *
     * @return
     */
    public static WechatOrderQueryReulst queryOrderByOrderId(String orderId) throws Exception {
        WechatOrderQuery wechatOrderQuery = new WechatOrderQuery();
        wechatOrderQuery.setOut_trade_no(orderId);
        wechatOrderQuery.setAppid(WechatConfigUtil.getAppId());
        wechatOrderQuery.setMch_id(WechatConfigUtil.getShopId());
        wechatOrderQuery.setNonce_str(MD5Util.CreateNoncestr().toUpperCase());

        String xml = getPayXml(MapUtil.bean2TreeMap(wechatOrderQuery));

        log.debug("prePay xml date:{}", xml);
        return WxHttpUtils.postForXml(ORDER_QUERY, xml, WechatOrderQueryReulst.class);

    }

    private static String getPayXml(TreeMap<String, String> treeMap) throws Exception {
        StringBuilder sb = new StringBuilder();
        for (String key : treeMap.keySet()) {
            if (StringUtils.isNotEmpty(treeMap.get(key))) {
                sb.append(key).append("=").append(treeMap.get(key)).append("&");
            }
        }
        sb.append("key=" + WechatConfigUtil.getShopSecrect());
        log.debug("pay sing url :{}", sb.toString());
        String sign = MD5Util.MD5Encode(sb.toString(), "utf-8").toUpperCase();
        log.debug("pay sign :{}", sign);
        StringBuilder xml = new StringBuilder();
        xml.append("<xml>\n");
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            if (StringUtils.isNotEmpty(entry.getValue())) {
                xml.append("<" + entry.getKey() + ">").append("<![CDATA[").append(entry.getValue()).append("]]>").append("</" + entry.getKey() + ">\n");
            }
        }
        xml.append("<sign>").append(sign).append("</sign>\n");
        xml.append("</xml>");
        return xml.toString();
    }


    private static String getPackage(PrePayInfo payinfo) throws Exception {
        if (payinfo.getAppId() == null || payinfo.getMch_id() == null || payinfo.getNonce_str() == null || payinfo.getBody() == null ||
                payinfo.getOut_trade_no() == null || payinfo.getTotal_fee() == null || payinfo.getSpbill_create_ip() == null || payinfo.getNotify_url() == null ||
                payinfo.getTrade_type() == null) {
            throw new Exception("payinfo param is null " + payinfo);
        }

        TreeMap<String, String> treeMap = new TreeMap<String, String>();
        treeMap.put("appid", payinfo.getAppId());
        treeMap.put("attach", payinfo.getAttach());
        treeMap.put("body", payinfo.getBody());
        treeMap.put("detail", payinfo.getDetail());
        treeMap.put("device_info", payinfo.getDevice_info());
        treeMap.put("fee_type", payinfo.getFee_type());
        treeMap.put("goods_tag", payinfo.getGoods_tag());
        treeMap.put("limit_pay", payinfo.getLimit_pay());
        treeMap.put("mch_id", payinfo.getMch_id());
        treeMap.put("nonce_str", payinfo.getNonce_str());
        treeMap.put("notify_url", payinfo.getNotify_url());
        treeMap.put("openid", payinfo.getOpenid());
        treeMap.put("out_trade_no", payinfo.getOut_trade_no());
        treeMap.put("product_id", payinfo.getProduct_id());
        treeMap.put("spbill_create_ip", payinfo.getSpbill_create_ip());
        treeMap.put("time_expire", payinfo.getTime_expire());
        treeMap.put("time_start", payinfo.getTime_start());
        treeMap.put("total_fee", payinfo.getTotal_fee());
        treeMap.put("trade_type", payinfo.getTrade_type());

        StringBuilder sb = new StringBuilder();
        for (String key : treeMap.keySet()) {
            if (StringUtils.isNotEmpty(treeMap.get(key))) {
                sb.append(key).append("=").append(treeMap.get(key)).append("&");
            }
        }
        sb.append("key=" + WechatConfigUtil.getShopSecrect());
        log.debug("prePay sing url :{}", sb.toString());
        String sign = MD5Util.MD5Encode(sb.toString(), "utf-8").toUpperCase();
        log.debug("prePay sign :{}", sign);
        StringBuilder xml = new StringBuilder();
        xml.append("<xml>\n");
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            if (StringUtils.isNotEmpty(entry.getValue())) {
                xml.append("<" + entry.getKey() + ">").append("<![CDATA[").append(entry.getValue()).append("]]>").append("</" + entry.getKey() + ">\n");
            }
        }
        xml.append("<sign>").append(sign).append("</sign>\n");
        xml.append("</xml>");
        return xml.toString();
    }

}
